<!--
 * @Description  :
 * @Version      : 1.0
 * @Author       : seraph
 * @Date         : 2024-12-13 16:10:18
 * @LastEditors  : seraph
 * @LastEditTime : 2024-12-24 19:03:01
-->
<template>
  <h3>v-on 修饰符</h3>
  <hr />
  <h4>事件修饰符</h4>
  <h4>
    浏览器的事件处理机制分为三个阶段：<span class="red">捕获阶段</span>、<span class="red">目标阶段</span>和<span
      class="red">冒泡阶段</span>。在默认情况下，当一个事件被触发时，浏览器会检查是否有事件处理程序可能会阻止事件的默认行为。对于像touchmove（触摸移动）和scroll（滚动）这类频繁触发的事件，这种检查机制会对性能产生影响。
  </h4>
  <h4>事件冒泡：子元素触发的事件会传播到父元素，父元素的点击事件也会执行。</h4>
  <h4>事件捕获：父元素触发的事件会先捕获到事件，然后才会触发子元素的点击事件。</h4>
  <h4>事件停止传播：使用 .stop 修饰符，可以阻止事件冒泡。</h4>
  <h4>事件阻止默认行为：使用 .prevent 修饰符，可以阻止默认行为。</h4>
  <h4>事件捕获：使用 .capture 修饰符，可以改变事件的处理顺序，使事件在捕获阶段而不是冒泡阶段被触发。</h4>
  <h4>只在自身触发：使用 .self 修饰符，可以只在自身触发。</h4>
  <h4>只触发一次：使用 .once 修饰符，可以只触发一次。</h4>
  <h4>passive 事件：使用 .passive 修饰符，可以告诉浏览器你不想阻止事件默认行为。</h4>
  <hr />

  <!-- TAG: ======================================================== -->
  <h4>.stop: 阻止事件冒泡。当事件发生在具有 .stop 修饰符的元素上时，它不会继续传播到父元素。</h4>
  <h4>下面这个例子中，没有加 .stop 修饰符的 button 点击事件会传播到父元素，导致父元素的点击事件也会执行。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click="doThat">子：doThat and doThis</button>you can click me</h4>
  <h4>加了 .stop 修饰符后，阻止了事件冒泡，父元素的点击事件不会被执行。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click.stop="doThat">子：only doThat</button>you can click me</h4>
  <hr>

  <h4>.prevent: 阻止默认事件。当事件发生在具有 .prevent 修饰符的元素上时，默认行为不会执行。</h4>
  <h4>下面这个例子中，没有加 .prevent 修饰符的 a 标签的默认行为是打开链接。</h4>
  <h4 class="bg-pink"><a href="https://www.baidu.com" title="can go to baidu" target="_blank" @click="doThat">can go to
      baidu</a></h4>
  <h4>加了 .prevent 修饰符，默认行为【url 跳转】不会执行。</h4>
  <h4 class="bg-pink"><a href="https://www.baidu.com" title="can't go to baidu" target="_blank"
      @click.prevent="doThat">can't go to baidu</a></h4>
  <hr>



  <h4>.capture: 添加事件捕获，它用于改变事件的处理顺序，使事件在捕获阶段而不是冒泡阶段被触发。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click="doThat">子：first doThat then doThis</button>you can click me</h4>
  <h4>加了 .capture 修饰符后，父元素会先捕获到事件，然后才会触发子元素的点击事件。</h4>
  <h4 class="bg-pink" @click.capture="doThis">父：<button @click="doThat">子：first doThis then doThat</button>you can click
    me
  </h4>
  <hr>

  <h4>.self: 只当事件发生在元素自身时触发处理函数。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click="doThat">子：doThat and doThis</button>you can click me</h4>
  <h4>加了 .self 修饰符后，仅当父元素被点击时，它的点击事件才会执行。它不会响应子元素的冒泡事件。</h4>
  <h4 class="bg-pink" @click.self="doThis">父：<button @click="doThat">子：only doThat</button>you can click me</h4>
  <hr>


  <h4>.once: 只触发一次。当事件发生在具有 .once 修饰符的元素上时，它只会触发一次。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click="doThat">子：you can click me more times</button>you can click
    me
  </h4>
  <h4>加了 .once 修饰符后，元素的点击事件只会触发一次。</h4>
  <h4 class="bg-pink" @click="doThis">父：<button @click.once="doThat">子：you can click me only once</button>you can click
    me</h4>
  <hr>

  <h4>.passive: 用于告诉浏览器这个事件处理器不会调用 preventDefault()，阻止滚动的默认行为。</h4>
  <div class="scroll-container">
    <div class="normal-scroll" @scroll="handleScroll">
      <h4>普通滚动 (无 .passive)</h4>
      <div v-for="i in 100" :key="i">Item {{ i }}</div>
    </div>

    <div class="passive-scroll" @scroll.passive="handleScroll">
      <h4>被动滚动 (有 .passive)</h4>
      <div v-for="i in 100" :key="i">Item {{ i }}</div>
    </div>
  </div>


  <hr />

</template>

<script lang="ts" setup>
import { ref, reactive, onMounted, watch, computed } from 'vue'

const doThat = () => {
  console.log(Date.now().toString().slice(-3), 'doThat')
  alert('子元素')
}

const doThis = () => {
  console.log(Date.now().toString().slice(-3), 'doThis')
  alert('父元素')
}


const handleScroll = (event: Event) => {
  setTimeout(() => {
    console.log(Date.now().toString().slice(-6), 'handleScroll')
  }, 3000)
}

</script>

<style scoped>
.bg-pink {
  background-color: #ffb2b2;
  padding: 5px;
}

#blue,
.blue {
  color: blue;
}

#red,
.red {
  color: red;
}

#green,
.green {
  color: green;
}

.bold {
  font-weight: bold;
}

/* Chrome, Safari, Edge, Opera */
#numInput[type="number"]::-webkit-outer-spin-button,
#numInput[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* firefox 兼容性 */
#numInput[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

button {
  margin-right: 10px;
  min-width: 80px;
  font-size: 16px;
  line-height: 150%;
}

.scroll-container {
  display: flex;
  gap: 20px;
}

.normal-scroll,
.passive-scroll {
  height: 200px;
  width: 200px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
